home *** CD-ROM | disk | FTP | other *** search
- /*
- * net.c
- *****************************************************************************
- * *
- * part of: *
- * TCP/UDP/ICMP/IP Network kernel for NCSA Telnet *
- * by Tim Krauskopf *
- * *
- * National Center for Supercomputing Applications *
- * 152 Computing Applications Building *
- * 605 E. Springfield Ave. *
- * Champaign, IL 61820 *
- *
- *****************************************************************************
- *
- * those generic tool-type things that only work on PCs.
- * includes all hardware-level calls to Ethernet that are unique to the PC
- *
- * Function pointers for Ether calls
- */
-
- /**********************************************************
- * Modified by Jamie Honan for use as UDP only.
- * Eventual goal - a boot prom
- * 13 Apr 1993 - strip out arp, bind with single hardware only
- * strip out references to config data structure,
- * ports data structure
- *
- ***********************************************************/
-
- #include "protocol.h"
- #include "bootinc.h"
-
-
- int SQwait = 0;
- int OKpackets = 0;
-
- /*
- * defined in assembly language file for interrupt driven Ether buffering
- *
- */
-
- unsigned char rstat; /* last status from read */
- char far *bufpt; /* current buffer pointer */
- char far *bufend; /* pointer to end of buffer */
- char far *bufread; /* pointer to where program is reading */
- char far *buforg; /* pointer to beginning of buffer */
-
- int bufbig, /* number of bytes currently
- * in buffer */
- buflim; /* max number of bytes in
- * buffer */
-
- #ifndef CONFIG_IRQ
- #define CONFIG_IRQ 5
- #endif
-
- #ifndef CONFIG_IOADDR
- #define CONFIG_IOADDR 0x280
- #endif
-
- #ifndef CONFIG_HADDR
- #define CONFIG_HADDR 0xd000
- #endif
-
- #ifndef CONFIG_EXTRA
- #define CONFIG_EXTRA 0
- #endif
-
-
-
- /*
- * Declare required Ethernet driver.
- * To add a driver, pick a unique 2 char prefix and declare your own
- * routines. I want to keep the same parameters for EVERY driver.
- * If your driver needs additional parameters, then see netconfig() below
- * for an indication of where to put custom board code.
- */
-
- typedef int (ETOPEN) (unsigned char far *s, unsigned int irq, unsigned int addr,
- unsigned int ioaddr);
-
- typedef int (GETADDR) (unsigned char far *s, unsigned int addr,
- unsigned int ioaddr);
-
- typedef int (SETADDR) (char far *s, int addr, int ioaddr);
-
- typedef int (ETCLOSE) (void);
-
- typedef int (XMIT) (DLAYER far * packet, int count);
-
- typedef void (RECV) (void);
-
- typedef void (ETUPDATE) (void);
-
-
- static ETOPEN *etopen;
- static GETADDR *getaddr;
- static SETADDR *setaddr;
- static ETCLOSE *etclose;
- static XMIT *xmit;
- static RECV *recv;
- static ETUPDATE *etupdate;
-
- #ifdef NET8003
-
- extern ETOPEN WDetopen;
- extern GETADDR WDgetaddr;
- extern SETADDR WDsetaddr;
- extern ETCLOSE WDetclose;
- extern XMIT WDxmit;
- extern RECV WDrecv;
- extern ETUPDATE WDetupdate;
-
- #elif defined NET3COM
-
- extern ETOPEN E3etopen;
- extern GETADDR E3getaddr;
- extern SETADDR E3setaddr;
- extern ETCLOSE E3etclose;
- extern XMIT E3xmit;
- extern RECV E3recv;
- extern ETUPDATE E3etupdate;
-
- #else
-
- ERROR : no ethernet interface defined
-
- /* and so on */
- #endif
-
- #ifdef THEM_ALL
-
- extern int E1etopen(), E1getaddr(), E1setaddr(), E1recv(), E1xmit(), E1etupdate(), E1etclose();
- extern int E3etopen(), E3getaddr(), E3setaddr(), E3recv(), E3xmit(), E3etupdate(), E3etclose();
- extern int E5etopen(), E5getaddr(), E5setaddr(), E5recv(), E5xmit(), E5etupdate(), E5etclose(), E5etdma();
- extern int ATetopen(), ATgetaddr(), ATrecv(), ATxmit(), ATetupdate(), ATetclose();
- extern int M5etopen(), M5getaddr(), M5recv(), M5xmit(), M5etupdate(), M5etclose();
- extern int M9etopen(), M9getaddr(), M9recv(), M9xmit(), M9etupdate(), M9etclose();
- extern int U1etopen(), U1getaddr(), U1recv(), U1xmit(), U1etupdate(), U1etclose();
- extern int U2etopen(), U2getaddr(), U2recv(), U2xmit(), U2etupdate(), U2etclose();
- extern int WDetopen(), WDgetaddr(), WDrecv(), WDxmit(), WDetupdate(), WDetclose();
- extern int E2etopen(), E2getaddr(), E2recv(), E2xmit(), E2etupdate(), E2etclose();
- extern int pketopen(), pkgetaddr(), pkxmit(), pketclose();
- extern void pkrecv(), pketupdate();
- extern int E4etopen(), E4getaddr(), E4recv(), E4xmit(), E4etupdate(), E4etclose();
-
- #endif
-
-
-
- /*************************************************************************/
- /* config network parameters
- * Set IRQ and DMA parameters for initialization of the adaptor
- */
- static uint nnirq = CONFIG_IRQ;
- static uint nnaddr = CONFIG_HADDR;
- static uint nnioaddr = CONFIG_IOADDR;
- static uint nnextra = CONFIG_EXTRA;
-
- int
- netparms(uint irq, uint address, uint ioaddr, uint extra)
- {
- nnirq = irq;
- nnaddr = address;
- nnioaddr = ioaddr;
- nnextra = extra;
- }
-
- /**********************************************************************/
- /* netconfig
- * load the function pointers for network access
- * Currently setaddr() is not used, so it isn't loaded.
- *
- * Note that netparms is called BEFORE netconfig. So if you have any
- * really special variables to set for your board that involve
- * irq,address and ioaddr, you can add calls to your special routines
- * in this section.
- *
- * Some drivers will do the interrupt driver and board initialization
- * in etopen() and some will do it in getaddr().
- */
- void
- netconfig(s)
- char *s;
- {
-
- #ifdef NET8003
-
- etopen = WDetopen;
- xmit = WDxmit;
- recv = WDrecv;
- getaddr = WDgetaddr;
- etupdate = WDetupdate;
- etclose = WDetclose;
-
- #elif defined NET3COM
-
- etopen = E3etopen;
- xmit = E3xmit;
- recv = E3recv;
- getaddr = E3getaddr;
- etupdate = E3etupdate;
- etclose = E3etclose;
- #else
- ERROR : no ethernet interface defined
- /* and so on */
- #endif
-
- #ifdef THEM_ALL
- if (!strncmp(s, "3c505", 5) || !strncmp(s, "505", 3))
- {
- etopen = E5etopen;
- xmit = E5xmit;
- recv = E5recv;
- getaddr = E5getaddr;
- etupdate = E5etupdate;
- etclose = E5etclose;
- } /* end if */
- else if (!strncmp(s, "star10", 6) || !strncmp(s, "starlan", 7))
- {
- etopen = ATetopen;
- xmit = ATxmit;
- recv = ATrecv;
- getaddr = ATgetaddr;
- etupdate = ATetupdate;
- etclose = ATetclose;
- } /* end if */
- else if (!strncmp(s, "packet", 6))
- {
- etopen = pketopen;
- xmit = pkxmit;
- recv = pkrecv;
- getaddr = pkgetaddr;
- etupdate = pketupdate;
- etclose = pketclose;
- }
- else if (!strncmp(s, "ni9", 3) || !strncmp(s, "92", 2))
- {
- etopen = M9etopen;
- xmit = M9xmit;
- recv = M9recv;
- getaddr = M9getaddr;
- etupdate = M9etupdate;
- etclose = M9etclose;
- }
- else if (!strncmp(s, "ni5", 3) || !strncmp(s, "mi", 2))
- {
- etopen = M5etopen;
- xmit = M5xmit;
- recv = M5recv;
- getaddr = M5getaddr;
- etupdate = M5etupdate;
- etclose = M5etclose;
- /*
- * special initialization call would go here
- */
- }
- else if (!strncmp(s, "nicps", 5))
- {
- etopen = U2etopen;
- xmit = U2xmit;
- recv = U2recv;
- getaddr = U2getaddr;
- etupdate = U2etupdate;
- etclose = U2etclose;
- }
- else if (!strncmp(s, "nicpc", 5) || !strncmp(s, "pcnic", 5))
- {
- etopen = U1etopen;
- xmit = U1xmit;
- recv = U1recv;
- getaddr = U1getaddr;
- etupdate = U1etupdate;
- etclose = U1etclose;
- }
- else if (!strncmp(s, "3c523", 5) || !strncmp(s, "523", 3))
- {
- etopen = E2etopen;
- xmit = E2xmit;
- recv = E2recv;
- getaddr = E2getaddr;
- etupdate = E2etupdate;
- etclose = E2etclose;
- }
- else if (!strncmp(s, "3c503", 5) || !strncmp(s, "503", 3))
- {
- etopen = E4etopen;
- xmit = E4xmit;
- recv = E4recv;
- getaddr = E4getaddr;
- etupdate = E4etupdate;
- etclose = E4etclose;
- E4setwire(nnextra * 2);
- }
- else if (!strncmp(s, "r501", 4))
- { /* special reserve driver */
- etopen = E3etopen;
- xmit = E3xmit;
- recv = E3recv;
- getaddr = E3getaddr;
- etupdate = E3etupdate;
- etclose = E3etclose;
- }
- else
- { /* default choice */
- etopen = E1etopen;
- xmit = E1xmit;
- recv = E1recv;
- getaddr = E1getaddr;
- etupdate = E1etupdate;
- etclose = E1etclose;
- }
- #else
- s = s; /* compiler warning */
- #endif
- }
-
- /**********************************************************************/
- int
- initbuffer()
- {
- bufpt = MK_FP(segds(), &raw[0]);
- bufread = buforg = bufpt; /* start at the beginning */
-
- bufbig = 0;
- bufend = &raw[RAW_END_LENGTH]; /* leave 2K breathing room, required */
- buflim = RAW_LIMIT_LENGTH; /* another 2K breathing room */
-
- (*getaddr) (nnmyaddr, nnaddr, nnioaddr);
-
- return (0);
- }
-
- /**********************************************************************/
- /* ethrecv
- * find ip packets in the buffer
- * modelled on demux
- *
- * returns non zero for ip packet available
- */
- int
- ethrecv(IPKT * p)
- {
- uint16 getcode;
- uint ulen;
- DLAYER *firstlook;
- int retcode;
-
- retcode = 0;
- if (!etupdate) /* check that network is hooked up */
- return (0);
- (*recv) (); /* NULL operation for 3COM */
- #ifdef nonononpo
- n_printf("After Masking!\n");
- n_printf("pt->%lp, read->%lp, end->%lp\n", bufpt, bufread, bufend);
- n_printf("\n HAHA \n");
- n_printf("bufbig = %d\n", bufbig);
- n_getch();
- #endif
- if (bufbig > 0)
- {
- ulen = *(uint16 *) (bufread);
- firstlook = (DLAYER *) (bufread + 2); /* where packet is */
- if (debug)
- {
- n_printf("RXING dest=%x.%x.%x.%x.%x.%x, me=%x.%x.%x.%x.%x.%x, type=%d\n",
- (unsigned int) firstlook->dest[0], (unsigned int) firstlook->dest[1], (unsigned int) firstlook->dest[2],
- (unsigned int) firstlook->dest[3], (unsigned int) firstlook->dest[4], (unsigned int) firstlook->dest[5],
- (unsigned int) firstlook->me[0], (unsigned int) firstlook->me[1], (unsigned int) firstlook->me[2],
- (unsigned int) firstlook->me[3], (unsigned int) firstlook->me[4], (unsigned int) firstlook->me[5],
- firstlook->type);
- n_printf("big=%d, size=%d\n", bufbig, ulen);
- }
- getcode = firstlook->type; /* where does it belong? */
- switch (getcode)
- { /* what to do with it? */
- case EARP:
- case ERARP:
- if (ulen > sizeof(IPKT))
- ulen = sizeof(IPKT);
- memcpy(p, firstlook, ulen);
- retcode = arpinterpret((ARPKT *)p);
- break;
-
- case EIP:
- if (ulen > sizeof(IPKT))
- {
- ulen = sizeof(IPKT);
- if (debug)
- n_printf("packet too long\n");
- }
- memcpy(p, firstlook, ulen);
- retcode = ulen;
- break;
-
- default:
- if (debug)
- n_printf("Not Arp or Ip packet\n");
- break;
- } /* end switch */
- (*etupdate) (); /* update read pointers in buffer, free
- * packet */
- }
- return (retcode);
- }
-
- /************************************************************************/
- /* dlayersend
- *
- * usage: err=dlayersend(ptr,size)
- * err=0 for successful, non-zero error code otherwise
- * ptr is to a dlayer packet header
- * size is the number of bytes total
- *
- * This particular dlayer routine is for Ethernet. It will have to be
- * replaced for any other dlayer.
- *
- * Ethernet addresses are resolved at higher levels because they will only
- * need to be resolved once per logical connection, instead of once per
- * packet. Not too layer-like, but hopefully modular.
- *
- */
-
- int
- dlayersend(ptr, size)
- DLAYER *ptr;
- unsigned size;
- {
- int ret,
- i;
-
- #ifdef OLD_WAY
- if (size < 60)
- size = 60;
- if (size & 0x01)
- size += 1;
- #else
- unsigned char *c;
-
- c = (unsigned char *) ptr;
- *(c + size++) = 0; /* NULL pad last char */
- *(c + size++) = 0; /* NULL pad last char */
- #endif
-
- for (i = 0; i < SQwait; i++);
- if ((++OKpackets) > 10)
- {
- SQwait -= 10;
- OKpackets = 0;
- }
- if (SQwait < 10)
- SQwait = 10;
-
- ret = (*xmit) ((DLAYER *) ptr, size); /* send it out, pass back
- * return code */
- /* xmit checks for size < 60 */
- /*
- * automatic, immediate retry once
- */
- if (ret)
- {
- if (ret == (*xmit) ((DLAYER *) ptr, size))
- netposterr(100); /* post user error message */
- }
- return (ret);
- }
-
- /***************************************************************************/
- /* dlayerinit
- * Do machine dependent initializations of whatever hardware we have
- * (happens to be ethernet board here )
- */
- int
- dlayerinit(void)
- {
- int my_var;
-
- if (initbuffer() || !etopen)
- return (-10);
-
- if (debug)
- {
- n_printf("nnirq=%x, nnaddr=%x, nnioaddr=%x\n", (uint16) nnirq, (uint16) nnaddr, (uint16) nnioaddr);
- }
- /*
- * Call (*etopen) first to be sure any board/driver initializations are taken care of
- */
- my_var = ((*etopen) (MK_FP(segds(), &nnmyaddr[0]), nnirq, nnaddr, nnioaddr));
- return my_var;
- }
-
- void
- dlayershut(void)
- {
- if (etclose)
- (*etclose) ();
- }
-
- /***************************************************************************/
- /* pcgetaddr
- * return results from indirect getaddr call.
- * This is a pc-specific request for the 48-bit address which was added
- * so that the user program could print the value.
- */
- void
- pcgetaddr(s, x, y)
- char *s;
- int x,
- y;
- {
- if (getaddr)
- (*getaddr) (s, x, y);
- }
-